package com.hmdp.utils.lock;

import cn.hutool.core.lang.UUID;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

public class SimpleRedisLock  implements  ILock {


    private StringRedisTemplate redisTemplate ;


    private String name  ;


    private static  final  String KEY_PREFIX = "lock: ";

    private static  final  String ID_PREFIX = UUID.randomUUID().toString(true)+"-";


    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT ;

    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();

        UNLOCK_SCRIPT.setLocation(new ClassPathResource("lua_scripts/unlock.lua"));

        UNLOCK_SCRIPT.setResultType(Long.class);
    }

    public SimpleRedisLock(StringRedisTemplate redisTemplate, String name) {

        this.redisTemplate = redisTemplate;
        this.name = name;
    }

    /**
     * 尝试获取锁
     * 锁持有的超时时间，过期后自动释放
     * true 代表获取锁成功，false 代表获取锁失败
     *
     * @param timeoutSec
     * @return
     */
    @Override
    public boolean tryLock(long timeoutSec) {
        // 获取线程的标识
        String threadId = ID_PREFIX +  Thread.currentThread().getId();
        // 尝试获取锁
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(aBoolean);
    }



    /**
     * 释放锁
     */
    @Override
    public void unlock() {
        // 获取线程的标识
        String threadId = ID_PREFIX +  Thread.currentThread().getId();
        String  key = KEY_PREFIX + name ;

        // 调用lua 脚本
        Long execute = redisTemplate.execute(UNLOCK_SCRIPT, Collections.singletonList(key), threadId);

    }


    /**
     * 释放锁
     */
//    @Override
    public void unlock02() {
        // 获取线程标识
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁中的标识
        String id = redisTemplate.opsForValue().get(KEY_PREFIX + name);

        // 判断标识是否一致
        if(threadId.equals(id)) {
            // 释放锁
            redisTemplate.delete(KEY_PREFIX + name);
        }
    }
}
